package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"regexp"
	"gopkg.in/yaml.v2"
)

func removeGroupBytes(str []byte, matchstr string) []byte {
	exp := regexp.MustCompile(matchstr)
	rldidx := exp.FindAllSubmatchIndex(str, -1)

	rltstr := []byte{}
	curIdx := 0
	for _, v := range rldidx {
		for i := 2; i <= len(v)-2; i += 2 {
			rltstr = append(rltstr, str[curIdx:v[i]]...)
			curIdx = v[i+1]
		}
		rltstr = append(rltstr, str[curIdx:v[1]]...)
		curIdx = v[1]
	}
	rltstr = append(rltstr, str[curIdx:]...)
	return rltstr
}

type Expconf struct {
	Match []Match `json:"match" yaml:"match"`
}

type Match struct {
	Expstr      string   `json:"expstr" yaml:"expstr"`
	GroupRemove []string `json:"group_remove" yaml:"group_remove"`
}

func ReadFromJsonFile(filename string) (Expconf, error) {
	bytes, err := ioutil.ReadFile(filename)
	if err != nil {
		return Expconf{}, err
	}

	var expconf Expconf
	err = json.Unmarshal(bytes, &expconf)

	fmt.Println("expconf:", expconf)
	return expconf, err
}

func ReadFromYamlFile(filename string) (Expconf, error) {
	bytes, err := ioutil.ReadFile(filename)
	if err != nil {
		return Expconf{}, err
	}

	var expconf Expconf
	err = yaml.Unmarshal(bytes, &expconf)

	// fmt.Println("expconf:", expconf)
	return expconf, err
}

func HandleExpconf(str []byte, expconf Expconf) []byte {
	for _, v := range expconf.Match {
		exp := regexp.MustCompile(v.Expstr)

		for _, v2 := range v.GroupRemove {
			str = exp.ReplaceAllFunc(str, func(s []byte) []byte {
				return removeGroupBytes(s, v2)
			})
		}
	}
	return str
}

func handleXcompiler(str []byte) []byte {
	exp := regexp.MustCompile(`-Xcompiler\s+[^\s]+`)

	// C500S-10817
	// 对mxcc来说，需要保持用户的原始意图，所以不适合对\"做进一步的适配。

	// wcuda看能否按下述方式处理一下：
	// 区分以下两种场景
	// -Xcompiler -D\"xxx\",-D\"yyy\" --> -Xcompiler -D\"xxx\",-D\"yyy\"
	// -Xcompiler \"-Dxxx\",\"-Dyyy\" --> -Xcompiler -Dxxx,-Dyyy
	// 对-Xcompiler的内容，以逗号分割成各单元，若单元以\"开头，就去掉该单元首尾的\"
	str = exp.ReplaceAllFunc(str, func(s []byte) []byte {
		return removeGroupBytes(s, `[,\s](\\)"[a-zA-Z0-9-]+(\\)"`)
	})

	// C500S-11780
	// -Wall,-Werror,-Wno-error="cpp,-Wno-error=parentheses"  去除 -Werror,
	str = exp.ReplaceAllFunc(str, func(s []byte) []byte {
		return removeGroupBytes(s, `-Xcompiler\s+(-Werror)$`)
	})

	str = exp.ReplaceAllFunc(str, func(s []byte) []byte {
		return removeGroupBytes(s, `[^\s]+(,-Werror)$`)
	})

	str = exp.ReplaceAllFunc(str, func(s []byte) []byte {
		return removeGroupBytes(s, `[,\s](-Werror,?)[\s\-\w]`)
	})

	// fmt.Println("rltstr:", string(rlt))
	return str
}

func main() {
	// read file to byte array : bytes_cmd
	bytes_cmd, err := os.ReadFile(os.Args[1])
	if err != nil {
		fmt.Println("read file error:", err)
		return
	}

	// fmt.Println("before:", string(bytes_cmd))
	// rltbytes := handleXcompiler([]byte(bytes_cmd))

	// read json file to struct : expconf
	// expconf, err := ReadFromJsonFile("conf_regex.json")

	maca_path := os.Getenv("MACA_PATH")
	cucc_path := os.Getenv("CUCC_PATH")
	yamlfile := maca_path + "/tools/cu-bridge/bin/conf_regex.yaml"
	if len(cucc_path) > 0 {
		yamlfile = cucc_path + "/bin/conf_regex.yaml"
	}

	if len(os.Args) > 3 {
		yamlfile = os.Args[3]
	}
	expconf, err := ReadFromYamlFile(yamlfile)
	if err != nil {
		fmt.Println("read json file error:", err)
		return
	}

	rltbytes := HandleExpconf(bytes_cmd, expconf)

	// write byte array to file
	err = os.WriteFile(os.Args[2], rltbytes, 0777)
	if err != nil {
		fmt.Println("write file error:", err)
		return
	}

	// fmt.Println("after :", string(rltbytes))
	// fmt.Println("write done")
}
